package service

import (
	"a-app/dao"
	"a-app/domain/entity"
	dom "a-common/domain"
	"a-common/utils/excel"
	"a-common/utils/oss"
	"errors"
	"fmt"
	"mime/multipart"
	"strconv"
	"strings"
	"sync"

	"github.com/gofiber/fiber/v2"
	"github.com/xuri/excelize/v2"
)

var (
	userServiceTemp *UserService
	appUserDao      = dao.NewAppUserDao()
	userServiceOnce sync.Once
)

type UserService struct{}

func NewAppUserService() *UserService {
	userServiceOnce.Do(func() {
		userServiceTemp = &UserService{}
	})
	return userServiceTemp
}

// List 分页
func (m *UserService) List(args *entity.UserDto) (dom.PageVo, error) {
	return appUserDao.List(args, false)
}

// Export 导出
func (m *UserService) Export(args *entity.UserDto) (*excelize.File, error) {
	pageVo, err := appUserDao.List(args, true)
	if err != nil {
		return nil, err
	}
	return excel.NormalDynamicExport(pageVo.Rows, "Sheet1", "用户表", "", true, false, map[string]string{})
}

// ImportTemplate 获取导入模板
// func (m *userService) ImportTemplate(c *fiber.Ctx) error {
// 	return c.SendFile("./uploads/template/user_temp.xlsx")
// }

// Import 导入
func (m *UserService) Import(file *multipart.FileHeader, updateSupport int, account string) (string, error) {
	// 打开数据流
	src, err := file.Open()
	if err != nil {
		return "", err
	}
	defer func(src multipart.File) {
		_ = src.Close()
	}(src)

	// 读取数据流
	f, err := excelize.OpenReader(src)
	if err != nil {
		return "", err
	}
	defer func() {
		if err := f.Close(); err != nil {
			fmt.Println(updateSupport, err)
		}
	}()

	importList := []entity.AppUserImportVo{}
	err = excel.ImportExcel(f, &importList, 1, 2)
	if err != nil {
		return "", err
	}
	return appUserDao.ImportData(updateSupport, importList, account)
}

// Get 查
func (m *UserService) Get(userId string, uid int64) (vo entity.AppUserPageVo, err error) {
	// 将字符串转换为int64
	uId, err := strconv.ParseInt(userId, 10, 64)
	if err != nil {
		return vo, err
	}
	return appUserDao.Get(uId)
}

// Del 删
func (m *UserService) Del(ids string) (int64, error) {
	return appUserDao.Del(ids)
}

// Add 增
func (m *UserService) Add(args *entity.UserDto, uid int64) error {
	// 校验账号是否重复
	has, err := appUserDao.CheckUserNameUnique(args.UserName, args.UserId)
	if err != nil {
		return err
	}
	if has {
		return errors.New("已存在账号")
	}
	// 校验昵称是否重复
	has, err = appUserDao.CheckNickNameUnique(args.NickName, args.UserId)
	if err != nil {
		return err
	}
	if has {
		return errors.New("已存在昵称")
	}
	// 校验号码是否重复
	has, err = appUserDao.CheckPhoneUnique(args.Phonenumber, args.UserId)
	if err != nil {
		return err
	}
	if has {
		return errors.New("已存在号码")
	}
	// 校验邮箱是否重复
	has, err = appUserDao.CheckEmailUnique(args.Email, args.UserId)
	if err != nil {
		return err
	}
	if has {
		return errors.New("已存在邮箱")
	}
	return appUserDao.Add(args)
}

// Edit 改
func (m *UserService) Edit(args *entity.UserDto, uid int64) error {
	// 校验昵称是否重复
	has, err := appUserDao.CheckNickNameUnique(args.NickName, args.UserId)
	if err != nil {
		return err
	}
	if has {
		return errors.New("已存在昵称")
	}
	// 校验号码是否重复
	has, err = appUserDao.CheckPhoneUnique(args.Phonenumber, args.UserId)
	if err != nil {
		return err
	}
	if has {
		return errors.New("已存在号码")
	}
	// 校验邮箱是否重复
	has, err = appUserDao.CheckEmailUnique(args.Email, args.UserId)
	if err != nil {
		return err
	}
	if has {
		return errors.New("已存在邮箱")
	}
	return appUserDao.Edit(args)
}

// ChangeStatus 切换状态
func (m *UserService) ChangeStatus(args *entity.UserDto, uid int64, account string) (int64, error) {
	return appUserDao.ChangeStatus(args.UserId, args.Status, account)
}

// ResetPwd 重置密码
func (m *UserService) ResetPwd(args *entity.UserDto, uid int64, account string) (int64, error) {
	return appUserDao.UpdatePwd(args.UserId, args.Password, account)
}

// UpdatePwd 修改密码
func (m *UserService) UpdatePwd(args *entity.UserDto, uid int64, account string) (int64, error) {
	vUser, err := appUserDao.Get(uid)
	if err != nil {
		return 0, err
	}
	// 校验旧密码
	if !cryptUtils.DeCrypt(vUser.Password, args.OldPassword) {
		return 0, errors.New("密码错误")
	}
	// 新旧密码不能一致
	if cryptUtils.DeCrypt(vUser.Password, args.NewPassword) {
		return 0, errors.New("新旧密码不能一致")
	}
	return appUserDao.UpdatePwd(uid, args.NewPassword, account)
}

// Avatar 头像上传
func (m *UserService) Avatar(file *multipart.FileHeader, uid int64, account string) (string, error) {
	// 创建保存上传文件的路径
	filePath := "/profile/avatar/" + account + "." + strings.Split(file.Filename, ".")[1]

	// 上传文件
	// err := utils.NewOssUtils().PutObject(filePath, file)
	err := oss.New().PutObject(filePath, file)
	if err != nil {
		return "", err
	}

	// 更新用户头像路径
	if err := appUserDao.EditByAvatar(uid, filePath); err != nil {
		return "", err
	}

	// 拼接返回文件访问路径
	return filePath, nil
}

// GetAvatar 获取头像
func (m *UserService) GetAvatar(c *fiber.Ctx) error {
	// 获取下载文件的路径
	filename := c.Params("*")
	filepath := "./uploads/profile/avatar/" + filename

	// 读取文件内容
	// file, err := os.ReadFile(filepath)
	// if err != nil {
	// 	res.ServerFail(c, res.FILE_ERR_READ, err)
	// }

	// 设置响应头，告诉浏览器这是一个可下载的文件
	// c.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filename))

	// return c.Send(file)
	return c.SendFile(filepath)
}

// Profile 查询用户个人信息
func (m *UserService) Profile(uid int64) (entity.AppUserPageVo, error) {
	return appUserDao.Get(uid)
}

// GetSelectList 获取用户下拉列表
func (m *UserService) GetSelectList() ([]entity.AppUserSelectListVo, error) {
	return appUserDao.GetSelectList()
}
